<?php
class Receipt extends DataObject implements PermissionProvider {
    private static $singular_name = "Receipt";
    private static $plural_name = "Receipts";

    private static $template = 'ReceiptTemplate';

    private static $db = array(
        'Reference' => 'Varchar',
        'TotalAmount' => 'Currency',
        'Currency' => 'Varchar',
        'Status' => "Enum(array('Pending', 'Partially Paid', 'Fully Paid', 'Voided'), 'Pending')",
        'PaidDate' => 'Datetime',
        'VoidedDate' => 'Datetime',
        'Remark' => 'Varchar'
    );

    private static $has_one = array(
        'TransactionType' => 'TransactionType',
        'Member' => 'Member'
    );

    private static $has_many = array('Payments' => 'Payment');

    private static $default_sort = "Created DESC";

    private static $searchable_fields = array(
    	'Created' => array(
			'field' => 'DateField',
			'filter' => 'DateMatchFilter'
		),
        'Reference',
        'TotalAmount' => array(
            'filter' => 'GreaterThanOrEqualFilter'
        ),
        'Status',
        'PaidDate' => array(
			'field' => 'DateField',
			'filter' => 'DateMatchFilter'
		),
		'VoidedDate' => array(
			'field' => 'DateField',
			'filter' => 'DateMatchFilter'
		),
        'TransactionType.Title'
    );

    private static $summary_fields = array(
    	'Created.Nice',
        'Reference',
        'TotalAmount',
        'Currency',
        'Status',
        'PaidDate.Nice',
        'VoidedDate.Nice',
        'Remark'
    );

    static function create_receipt($data, $memberid) {
        return Receipt::create()->update($data)->setField('MemberID', $memberid)->write();
    }

    static function update_status($id, $status, $remark = false) {
        $receipt = Receipt::get()->byID($id);
        if($receipt->Status == 'Pending' && ($status == 'Partially Paid' || $status == 'Fully Paid')) {
            $receipt->PaidDate = SS_Datetime::now()->getValue();
        }
        if($status == 'Voided') {
            $receipt->VoidedDate = SS_Datetime::now()->getValue();
        }
        if($remark !== false) {
            $receipt->Remark = $remark;
        }
        $receipt->Status = $status;
        $receipt->write();
        return $receipt->ID;
    }

    /**
     * Generate reference for receipt
     * @return str Returns the reference
     */
    static function reference_generator() {
        $reference = rand(1, 99999999);
        $reference = str_pad($reference, 8, "0", STR_PAD_LEFT);
        while($result = DataObject::get_one("Receipt", "Reference = '{$reference}'")) {
            $reference = rand(1, 999999999);
            $reference = str_pad($reference, 8, "0", STR_PAD_LEFT);
        }
        return $reference;
    }

    /**
     * Set order invoice template
     *
     * @param $set_template string
     */
    static function set_template($set_template) {
        Config::inst()->update('Receipt', 'template', $set_template);
    }

    /**
     * Get order invoice template
     *
     * @param string
     */
    static function get_template() {
        return Config::inst()->get('Receipt', 'template');
    }

    function populateDefaults() {
        parent::populateDefaults();
        $this->Currency = SiteCurrencyConfig::current_site_currency();
    }

    public function fieldLabels($includerelations = true) {
        $labels = parent::fieldLabels($includerelations);

		$labels['Created'] = _t('Receipt.DATE', 'Date');
        $labels['Created.Nice'] = _t('Receipt.DATE', 'Date');
        $labels['Reference'] = _t('Receipt.REFERENCE', 'Reference');
        $labels['TotalAmount'] = _t('Receipt.TOTAL_AMOUNT', 'Total Amount');
        $labels['Currency'] = _t('Receipt.CURRENCY', 'Currency');
        $labels['Status'] = _t('Receipt.STATUS', 'Status');
        $labels['PaidDate'] = _t('Receipt.PAID_DATE', 'Paid Date');
        $labels['PaidDate.Nice'] = _t('Receipt.PAID_DATE', 'Paid Date');
        $labels['VoidedDate'] = _t('Receipt.VOIDED_DATE', 'Voided Date');
        $labels['VoidedDate.Nice'] = _t('Receipt.VOIDED_DATE', 'Voided Date');
        $labels['Remark'] = _t('Receipt.REMARK', 'Remark');
        $labels['TransactionType.Title'] = _t('Receipt.TRANSACTION_TYPE', 'Transaction Type');
		$labels['Payments'] = _t('Receipt.PAYMENT_METHOD', 'Payment Method');

        return $labels;
    }

    function getCMSFields() {
        $fields = parent::getCMSFields();

        if($this->exists()) {
        	$fields->dataFieldByName('Payments')->getConfig()
            ->removeComponentsByType('GridFieldAddExistingAutocompleter')
			->removeComponentsByType('GridFieldDetailForm')
            ->addComponent(new PaymentGridFieldDetailForm());
			
            $custom_fields = FieldList::create(LiteralField::create('Statement', $this->ViewHTML()));

            if($this->Status != 'Voided') {
                $custom_fields->push(TextField::create('Remark', $this->fieldLabel('Remark')));
            }

			$tab = $fields->findOrMakeTab('Root.Main');
			$tab->setChildren($custom_fields);
        }

        return $fields;
    }

    function updateTransactionType($code) {
        $this->TransactionTypeID = TransactionType::get_id_by_code($code);
        return $this;
    }

    function addPayment($payment_method, $data) {
    	foreach($data as $key => $val){
    		if(preg_match(sprintf('/%s_/i', $payment_method), $key)){
    			$data[str_replace(sprintf('%s_', $payment_method), '', $key)] = $val;
    		}
    	}
        $payment = singleton($payment_method)->update($data)->setField('ReceiptID', $this->ID);
        $payment->write();
        return $payment;
    }

    function processPaymentStatus() {
        $total_paid = $this->Payments()->filter('Status', 'Success')->sum('Amount');
        if($total_paid >= $this->TotalAmount) {
            $this->PaidDate = SS_Datetime::now()->getValue();
            $this->Status = 'Fully Paid';
        } else if($total_paid > 0 && $total_paid < $this->TotalAmount) {
            $this->Status = 'Partially Paid';
        }

        $this->write();
        return $this;
    }

    function onBeforeWrite() {
        parent::onBeforeWrite();
        if($this->Reference == '') {
            $this->Reference = Receipt::reference_generator();
        }
    }

    function getFullDetailHTML() {
        $template = new SSViewer('ReceiptDetail');
        $template->includeRequirements(false);
        return $this->renderWith($template);
    }

    function ViewHTML() {
        $template_ss = self::get_template();
        $this->PrintTime = SS_Datetime::now()->Nice();
        $this->Format = 'HTML';
        $this->SiteConfig = SiteConfig::current_site_config();
        $template = new SSViewer($template_ss);
        $template->includeRequirements(false);
        return $this->renderWith($template);
    }

    function ViewPDF() {
    	if($this->config()->allowed_pdf && class_exists('SS_DOMPDF')){
	        $template_ss = self::get_template();
	        $this->PrintTime = SS_Datetime::now()->Nice();
	        $this->Format = 'PDF';
	        $this->SiteConfig = SiteConfig::current_site_config();
	        $template = new SSViewer($template_ss);
	        $template->includeRequirements(false);
			$pdf = new SS_DOMPDF();
			$pdf->setHTML($this->renderWith($template));
			$pdf->render();
			return $pdf->stream(sprintf('receipt_%s.pdf', $this->Reference));
		}
    }

    function ViewPrint() {
        $template_ss = self::get_template();
        $this->PrintTime = SS_Datetime::now()->Nice();
        $this->Format = 'PRINT';
        $this->SiteConfig = SiteConfig::current_site_config();
        $template = new SSViewer($template_ss);
        $template->includeRequirements(false);
        return $this->renderWith($template);
    }

    function getTitle() {
        return 'Receipt Reference : ' . $this->Reference . ' (' . $this->obj('Created')->Nice() . ')';
    }

    function canView($member = false) {
        $extended = $this->extendedCan(__FUNCTION__, $member);
        if($extended !== null) {
            return $extended;
        }
        return Permission::check('VIEW_Receipt');
    }

    function canEdit($member = false) {
        return $this->canVoid($member);
    }

    function canDelete($member = false) {
        return false;
    }

    function canCreate($member = false) {
        return false;
    }
	
	function canPrint($member = false) {
        $extended = $this->extendedCan(__FUNCTION__, $member);
        if($extended !== null) {
            return $extended;
        }
        return Permission::check('PRINT_Receipt');
    }
	
	function canVoid($member = false) {
        $extended = $this->extendedCan(__FUNCTION__, $member);
        if($extended !== null) {
            return $extended;
        }
        return Permission::check('VOID_Receipt');
    }

    public function providePermissions() {
        return array(
            'VIEW_Receipt' => array(
                'name' => _t('Receipt.PERMISSION_VIEW', 'Allow view access right'),
                'category' => _t('Receipt.PERMISSIONS_CATEGORY', 'Receipt')
            ),
            'PRINT_Receipt' => array(
                'name' => _t('Receipt.PERMISSION_PRINT', 'Allow print access right'),
                'category' => _t('Receipt.PERMISSIONS_CATEGORY', 'Receipt')
            ),
            'VOID_Receipt' => array(
                'name' => _t('Receipt.PERMISSION_VOID', 'Allow void access right'),
                'category' => _t('Receipt.PERMISSIONS_CATEGORY', 'Receipt')
            )
        );
    }

}
?>